package com.zrx.govern.component.easyexcel.starter.utils;


import com.zrx.govern.component.easyexcel.starter.constants.ExcelCheckConstants;
import com.zrx.govern.component.easyexcel.starter.config.ExcelConfigProperties;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * zip解压缩工具类
 *
 * @author zhangxiaowei
 * @version V1.0
 **/

@Slf4j
public class FileZipUtil {

    @Getter
    @Setter
    private static String excelPath;
    /**
     * @param inputFileName 你要压缩的文件夹(整个完整路径)
     * @param zipFileName   压缩后的文件(整个完整路径)
     * @throws Exception
     */
    public static Boolean zip(String inputFileName, String zipFileName) throws Exception {
        zip(zipFileName, new File(inputFileName));
        return true;
    }

    /**
     * 将多个文件写入zip并下载此zip文件
     *
     * @param files       多个文件路径集合
     * @param zipFileName zip文件名 xx.zip
     * @param response
     * @return: void
     * @author zhangxiaowei
     **/
    public static void downloadZipFile(List<String> files, String zipFileName, HttpServletResponse response, ExcelConfigProperties properties) {
        File zipFile = null;
        try {
            if (!zipFileName.endsWith(ExcelCheckConstants.ZIP_FILE)) {
                throw new RuntimeException(String.format("非法的zip文件：%s",zipFileName));
            }
            /*拼接zip路径*/
            String zipFilePath = excelPath + File.separator + properties.getFileTempPath() + File.separator + zipFileName;
            zipFile = new File(zipFilePath);
            if (!zipFile.getParentFile().exists()) {
                zipFile.getParentFile().mkdirs();
            }
            if(!zipFile.exists()){
                zipFile.createNewFile();
            }
            /*1.生成zip文件*/
            buildManyFile2Zip(files, zipFile);
            /*2.读取zip文件，输出zip流对象*/
            InputStream bis = new FileInputStream(zipFile);
            response.setContentType("application/x-download");
            response.setCharacterEncoding("utf8");
            zipFileName = URLEncoder.encode(zipFileName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + zipFileName);
            response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            int len = 0;
            byte[] arr = new byte[1024];
            while ((len = bis.read(arr)) != -1) {
                out.write(arr,0,len);
                out.flush();
            }
            out.close();
            bis.close();
        } catch (Exception e) {
            log.error("zip文件下载失败", e);
            throw new RuntimeException(e);
        } finally {
            //zip文件删除
            if (zipFile != null) {
                zipFile.delete();
            }
        }

    }

    /**
     * 生成zip文件
     *
     * @param files
     * @param zipFile
     * @throws Exception
     */
    private static void buildManyFile2Zip(List<String> files, File zipFile) {
        List<File> fileList = new ArrayList<>(files.size());
        try {
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
            File file = null;
            for (String filePath : files) {
                file = new File(filePath);
                if (!file.isFile()) {
                    throw new RuntimeException("非法的file文件路径");
                }
                fileList.add(file);
                zip(out, file);
            }
            out.flush();
            out.close();
        } catch (Exception e) {
            log.error("zip文件生成异常", e);
            throw new RuntimeException(e);
        } finally {
            /*zip文件生成后,file文件删除*/
            for (File file : fileList) {
                file.delete();
            }
        }

    }

    private static void zip(String zipFileName, File inputFile) throws Exception {
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
        zip(out, inputFile);
        out.flush();
        out.close();
    }

    /**
     * 生成zip文件
     * @param out
     * @param f
     * @throws Exception
     */
    private static void zip(ZipOutputStream out, File f) throws Exception {
        if (f.isDirectory()) {
            File[] fl = f.listFiles();
            for (int i = 0; i < fl.length; i++) {
                if (fl[i].isFile()) {
                    zip(out, fl[i]);
                }
            }
        } else {
            out.putNextEntry(new ZipEntry(f.getName()));
            FileInputStream in = new FileInputStream(f);
            int b;
            while ((b = in.read()) != -1) {
                out.write(b);
            }
            in.close();
        }
    }

    public static void main(String[] temp) {
        try {
            //你要压缩的文件夹      和  压缩后的文件
            zip("E:\\ftl", "E:\\test.zip");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}